#include "AlienGenTcpServer.h"

AlienGenTcpServer::AlienGenTcpServer(int port, AlienGenNetHandler& handler, QObject *parent)
:QThread(parent),AlienGenIO(),_port(port),_handler(handler)
{

}

AlienGenTcpServer::~AlienGenTcpServer(void )
{

}

void AlienGenTcpServer::run()
{
    //struct fd_set read_fds;
    SOCKET	listener, newfd;
    struct	sockaddr_in myaddr, remoteaddr;
    struct timeval timeOut;
    int addrlen = sizeof(remoteaddr);
    int yes = 1, ret;

    qDebug() << "Starting Server on port " << _port;

    if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        qDebug() << "Cannot create socket";
        return;
    }

    if( (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(int)) == -1)) {
        qDebug() << "setsockopt returns error";
        closesocket(listener);
        return;
    }

    myaddr.sin_family = AF_INET;
    myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    myaddr.sin_port = htons(_port);
    memset(&(myaddr.sin_zero), 0,8);

    if (bind(listener, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1) {
        qDebug() << "bind returns error";
        closesocket(listener);
        return;
    }

    if (listen(listener, 10) == SOCKET_ERROR) {
        qDebug() << "listen returns error";
        closesocket(listener);
        return;
    }

    _handler.start();

    qDebug() << "Server Ready !";

    do {

        FD_ZERO(&_master);
        FD_SET(listener, &_master);

        timeOut.tv_sec = 1;
        timeOut.tv_usec = 0;

        if((ret = select(FD_SETSIZE, &_master, NULL, NULL, &timeOut)) <= 0) {
            if(ret < 0)
                qDebug() << "select returns error";
            continue;
        }


        qDebug() << "Listening socket is readable.";
        newfd = accept(listener, (struct sockaddr*)&remoteaddr, (socklen_t*)&addrlen);

        if(newfd < 0) {
                qDebug() << "Accept returns error " << errno;
                continue;
        }

        char ipAddress[INET6_ADDRSTRLEN];
        inet_ntop(remoteaddr.sin_family, (struct sockaddr *)&remoteaddr.sin_addr, ipAddress, sizeof ipAddress);

        qDebug() << "Client request from " << ipAddress;

        qDebug() << "Descriptor " << newfd << " is readable.";
        _handler.onConnect(newfd);

    } while(!this->isInterruptionRequested());

    _handler.stop();

    qDebug() << "Stopping server !";
    closesocket(listener);
}
